package com.inspur.edp.bef.core.validation;

import com.inspur.edp.bef.api.action.validation.IValidationContext;
import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.api.message.IBizMessage;
import com.inspur.edp.cef.api.message.MessageLevel;
import com.inspur.edp.cef.core.i18n.I18nResourceUtil;
import com.inspur.edp.cef.spi.scope.AbstractCefScopeExtension;
import com.inspur.edp.svc.reference.check.api.CheckResult;
import com.inspur.edp.svc.reference.check.api.IReferenceCheckService;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

public class DeleteCheckExtension extends AbstractCefScopeExtension {

  private static final int BATCH_COUNT = 500;
  private static final double BATCH_THREHOLD_RATE = 2d / BATCH_COUNT;//当被引用数据量超过此比例后取消批量判断退化为逐个判断

  @Override
  public void onSetComplete() {
    List<DeleteCheckScopeNodeParameter> pars = getParamsGeneric();
    Map<String, List<DeleteCheckScopeNodeParameter>> group = pars.stream()
        .collect(Collectors.groupingBy(par -> par.getSource()));
    IReferenceCheckService service = SpringBeanUtils.getBean(IReferenceCheckService.class);
    for (Entry<String, List<DeleteCheckScopeNodeParameter>> groupEntry : group.entrySet()) {
      List<DeleteCheckScopeNodeParameter> parList = groupEntry.getValue();
      if (parList == null || parList.isEmpty()) {
        continue;
      }
      RefObject<IBizMessage> refMsg = new RefObject<>(null);
      int threhold = (int) (parList.size() * BATCH_THREHOLD_RATE);
      int referedCount = 0;
      ArrayList<String> batchIds = new ArrayList<>(Math.min(parList.size(), BATCH_COUNT));
      for (int i = 0; i < parList.size(); i++) {
        if (referedCount > threhold) {
          checkSingle(service, groupEntry.getKey(), parList.get(i).getContext(), refMsg);
        } else {
          batchIds.add(parList.get(i).getContext().getBEContext().getID());
          if (batchIds.size() >= BATCH_COUNT || i >= parList.size() - 1) {
            CheckResult result = service
                .checkReference(groupEntry.getKey(), batchIds.toArray(new String[]{}));
            if (result != null && result.isReferenced()) {
              for (int j = i - batchIds.size() + 1; j <= i; j++) {
                if (checkSingle(service, groupEntry.getKey(), parList.get(j).getContext(),
                    refMsg)) {
                  referedCount++;
                }
              }
            }
            batchIds.clear();
          }
        }
      }
      if (refMsg.argvalue != null) {
        parList.get(0).getContext().addMessage(refMsg.argvalue);
      }
    }
  }

  private boolean checkSingle(IReferenceCheckService service, String source,
      IValidationContext ctx, RefObject<IBizMessage> existing) {
    CheckResult result = service.checkReference(source, ctx.getBEContext().getID());
    if (result == null || !result.isReferenced()) {
      return false;
    }
    if (existing.argvalue != null) {
      existing.argvalue.getLocation().getDataIds().add(ctx.getBEContext().getID());
    } else {
      existing.argvalue = ctx.createMessageWithLocation(
          MessageLevel.Error, null, buildMessage(result), null);
    }
    return true;
  }

  private static String buildMessage(CheckResult result) {
    //TODO: Gsp_Cef_DelVal_0002考虑废弃
//    String warningMessage1 = I18nResourceUtil
//        .getResourceItemValue("pfcommon", "cef_exception.properties", "Gsp_Cef_DelVal_0002");
    List<String> resultWarningMessages = result.getWarningMessages();
    if (resultWarningMessages == null) {
      return getDefaultMessage();
    }
    StringBuilder stringBuilder = new StringBuilder();
    for (String warningMessageTemp : resultWarningMessages) {
      if (warningMessageTemp != null) {
        stringBuilder.append(warningMessageTemp);
      }
    }
    if (stringBuilder.length() == 0) {
      return getDefaultMessage();
    } else {
      return stringBuilder.toString();
    }
  }

  private static String defaultMessage = null;

  private static String getDefaultMessage() {
    if (defaultMessage != null) {
      return defaultMessage;
    }
    synchronized (DeleteCheckExtension.class) {
      if (defaultMessage != null) {
        return defaultMessage;
      }
      defaultMessage = I18nResourceUtil
          .getResourceItemValue("pfcommon", "cef_exception.properties", "Gsp_Cef_DelVal_0001");
      return defaultMessage;
    }
  }
}
